<%
' +----------------------------------------------------------------------
' | POPASP [ ASP MVC ]
' +----------------------------------------------------------------------
' | Copyright (c) 2016 http://popasp.com All rights reserved.
' +----------------------------------------------------------------------
' | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
' +----------------------------------------------------------------------
' | Author: popasp <1737025626@qq.com>
' +----------------------------------------------------------------------
Class POPASP_MVC
	'在本类中不能使用array函数
	private c,a		' 控制器与方法名	
	Private dict_auto_key			' 用于K_函数的自动增长的键值
	public mvc_dir,config		' dict对象
	public dG_,dN_,dL_			'对应获取函数G_、N_
	public Version
	Public dRejection	' 反射类，以及寄存器
	Public dSql,dTpl,dFlow,dTime,dMd5		' 存储sql、模板引擎信息、流程、性能(耗时)
	Public dClass		' 存储实例化的类
	Public dModel		' 存储实例化的model
	Public dDict		' 存储实例化的Dictionary对象，可自动销毁
	Public dMSSoft		' 存储实例化的微软软件，比如Excel.Application
	Public fso,stream,reg	' Server.createObject("Scriptint.FileSystemObject")、RegExp对象
	Public Apt,Dict,File,Url,Uploader,Arr,[String],dbTOOL	' 具体的类 Application、POPASP_DICTIONARY、POPASP_FILE、POPASP_FILE,POPASP_MOLIBUPLOAD,POPASP_ARR
	Public isExecuteExtends		'是否在使用 Action_ 方法时，执行继承类的方法 initialize
	Private objExtendsClass,action_count,is_init_popasp		' 继承类的实例化
	Private isExit
	
	public Sub init
		if not is_init_popasp Then
			Easp.Json.EncodeUnicode = false
			
			'加载 POPASP_STRING 类
			set [String] = import("POPASP_STRING")			
			
			'加载 POPASP_DICTIONARY 类
			set Dict = import("POPASP_DICTIONARY")
			
			'加载 POPASP_ARR 类
			set Arr = import("POPASP_ARR")			
			
			' 加载 POPASP_CONFIG 类	
			call import("POPASP_CONFIG").import_config( mvc_dir & "popasp.convention.asp"  )
			call import("POPASP_CONFIG").import_config( APP_PATH & "/Conf/config.asp"  )
			
			
			set dRejection = CreateDict()
			
			' 加载 POPASP_FILE 类
			set File = import("POPASP_FILE")
			
			' 加载 POPASP_URL 类
			set Url = import("POPASP_URL")
			
			is_init_popasp = true
		end If
	End Sub
	
	Public Function pushTime( startTime , text )
		dim spent
		spent = FormatNumber( (timer() - startTime ) *1000,0,-1,0,0)
		if not isEmpty( dTime ) then
			if spent > 2 then
				dTime.add dTime.count , text & " " & spent & "ms"
			end if
		end if
		pushTime = spent
	end Function
	
	Public Function Logo()
		Logo = file_get_contents( mvc_dir & "Tpl/logo.txt" )
	End Function
	
	' 使用该方法与D_函数创建的Dictionary对象，程序结束时均可自动销毁
	Public Function CreateDict()
		dim count
		count = dDict.Count
		set dDict( count + 1 ) = Server.CreateObject("Scripting.Dictionary")
		Set CreateDict = dDict( count + 1 )
	End Function
	
	'检测组件是否安装
	Public Function IsInstall(Byval s)
		On Error Resume Next : Err.Clear()
		IsInstall = False
		Dim obj : Set obj = Server.CreateObject(s)
		If Err.Number = 0 Then IsInstall = True
		Set obj = Nothing : Err.Clear()
	End Function
	
	public function import_config( file_path )
		import_config = import("POPASP_CONFIG").import_config(file_path)
	End function
	
	'获取框架目录
	private function get_mvc_dir()
		dim file,contents,matches
		file = Request.ServerVariables("SCRIPT_NAME")
		contents = file_get_contents(file)
		reg.Global = false : reg.IgnoreCase = true : reg.MultiLine = false
		reg.Pattern = "<!--#include\s+file=\W(.*)popasp.asp\W\s*-->"
		
		if reg.test(contents) Then
			set matches = reg.execute( contents )
			get_mvc_dir = matches(0).subMatches(0)
		else
			call [Exit]("找不到popasp目录")
		End if
	End Function
	
	Function getModelRunName( ByVal tableName )
		tableName = UCFirst(LCase(tableName))
		getModelRunName = "M" & md5( C_("DB_TYPE") & C_("DB_PATH") & tableName )
	End Function
	
	'获取 TableModel.class.asp 的路径
	'先找 /home/Model/access/db/TableModel.class.asp
	'再找 /home/Model/access/TableModel.class.asp
	'再找 /home/Model/db/TableModel.class.asp
	'最后找 /home/Model/TableModel.class.asp
	'找不到返回空字符串
	Function getModelPath( byval tableName )
		on error resume next
		dim modelPath,db_type,db_path,ext
		db_type = LCase( C_("DB_TYPE") )
		db_path = File.baseName( LCase( C_("DB_PATH") ) )
		ext = File.extName( LCase( C_("DB_PATH") ) )
		db_path = mid( db_path,1,len(db_path) - len(ext) )
		tableName = UCFirst(LCase(tableName)) & "Model.class.asp"
		
		getModelPath = ""
		
		modelPath = APP_PATH & "/Model/" & db_type & "/" & db_path & "/" & tableName '如./home/Model/excel/15251成绩/1学期Model.class.asp		
		
		if file.isFile( modelPath ) then
			getModelPath = modelPath : exit Function
		end if
		
		modelPath = APP_PATH & "/Model/" & db_type  & "/" & tableName '如./home/Model/excel/1学期Model.class.asp
		
		if file.isFile( modelPath ) then
			getModelPath = modelPath : exit Function
		end if
		
		modelPath = APP_PATH & "/Model/" & db_path & "/" & tableName '如./home/Model/15251成绩/1学期Model.class.asp
		
		if file.isFile( modelPath ) then
			getModelPath = modelPath : exit Function
		end if
		
		modelPath = APP_PATH & "/Model/"  & tableName '如./home/Model/1学期Model.class.asp
		
		if file.isFile( modelPath ) then
			getModelPath = modelPath : exit Function
		end if
	End Function
	
	Function getModelDstPath( ByVal tableName )	
		tableName = UCFirst(LCase(tableName))
		getModelDstPath = APP_PATH & "/Runtime/Class/" & getModelRunName( tableName ) & "Model.class.asp"
	End Function
  
	Private Sub Class_Initialize
		'Application.Contents.RemoveAll		
		set dDict = Server.CreateObject("Scripting.Dictionary")
		set dClass = CreateDict()
		set dModel = CreateDict()
		set dMSSoft = CreateDict()
		set dN_ = CreateDict()
		set dL_ = CreateDict()
		
		set reg = new RegExp		
		mvc_dir = get_mvc_dir()
		
		'设置'easp.asp'文件在网站中的路径
		Easp.BasePath = mvc_dir & "easyasp/"
		
		' 初始化Easp的插件目录
		Easp.PluginPath = mvc_dir & "easyasp/plugin/"
		
		set fso = Server.CreateObject("Scripting.FileSystemObject")
		
		set config = CreateDict()
		reg.Global = true : reg.IgnoreCase = true : reg.MultiLine = true
		reg.Pattern = ""

		dict_auto_key = 0
		isExecuteExtends = True
		
		set dSql = CreateDict()
		set dTpl = CreateDict()
		set dFlow = CreateDict()
		set dTime = CreateDict()
		set dMd5 = CreateDict()
		is_init_popasp = false
		
		Version = "1.0"
		
		isExit = true
	End Sub	
	
	Private Sub Class_Terminate
		on error resume next
		isExit = false
		dim key
		set fso = nothing
		set reg = nothing
		set config = nothing
		set dG_ = nothing
		set dN_ = nothing
		set Apt = nothing
		set Dict = nothing
		set File = nothing
		set Url = nothing
		set Uploader = nothing
		set objExtendsClass = Nothing
		call quit
	End Sub
	
	
	
	
	
	
	
	
	
	Private Sub init_uploader
		If isEmpty( Uploader ) Then
			set Uploader = import("POPASP_MOLIBUPLOAD")
		End If
		Uploader.AllowFileTypes = "*.*"
		Uploader.AllowMaxFileSize = "100MB"
		Uploader.AllowMaxSize = "100mb"
		Uploader.CharSet = "utf-8"	
		Uploader.SavePath = "./Upload"
	End Sub
	
	'将字符串首字母大写，popjb.com增加
	Function UCFirst(ByVal str)
		UCFirst = Me.String.UCFirst(str)		
	End Function 	
	
	'采用递归，删除str左边出现的字符串find
	function [ltrim](str,find)
		[ltrim] = Me.String.ltrim(str,find)
	End Function
	
	'采用递归，删除str右边出现的字符串find
	function [rtrim](str,find)
		[rtrim] = Me.String.rtrim(str,find)
	End Function
	
	'采用递归，删除str两端出现的字符串find
	function [trim](str,find)
		[trim] = Me.String.trim(str,find)
	End Function
	
	'对server.urlencode函数的解码
	function URLDecode(ByVal input)
		URLDecode =  Me.String.URLDecode(input)
	End function
	
	' 前台表单用method="post" enctype="multipart/form-data"发送，后台用POPASP_MOLIBUPLOAD接收
	' 如果key="" 则取得整个Post(Dictionary对象)，否则返回单个值
	Public Function Post(key)	
		On error resume next
		call init_uploader
		if not Uploader.GetData() Then exit Function		
		select case key
			case "","-1"
				set Post = Uploader.post("-1")
			case else
				if isObject( Uploader.post(key) ) Then
					set Post = Uploader.post(key)
				Else 
					Post = Uploader.post(key)
				End If				
		End select
	End Function
	
	' 文件采用自动命名的方式，自动上传到了Upload文件夹下
	Function Upload(formName)
		on error resume next
		dim File
		call init_uploader		
		Set File = Uploader.Save(formName,0,true)	
		if File.Succeed Then			
			Upload = File.FileName			
		Else 
			call L_( File.Exception )
		End If
		set File = Nothing		
	End Function
	
	'是否是POPASP_ 开头的类名
	Function isPopasp( className )
		isPopasp = ( UCase(Left( className , 7)) = "POPASP_" )
	End Function
	
	'是否是Action结尾的类名
	Function isAction( classname )
		isAction = ( UCase(Right( className , 6)) = "ACTION" )
	End Function
	
	'是否是Model结尾的类名
	Function isModel( className )
		isModel = ( UCase(Right( className , 5)) = "MODEL" AND UCase(className) <> "POPASP_MODEL" )
	End Function
	
	Function getDictAutoKey()
		getDictAutoKey = CStr(dict_auto_key)
		dict_auto_key = dict_auto_key + 1
	End Function
	
	'将 Request.Form中的数据转化成dict对象
	Function Form2Dict()
		dim key
		set Form2Dict = POP_MVC.dict.Create()
		for each key in Request.Form
			if isArray( Request.Form(key) ) then
				POP_MVC.dict.edit Form2Dict,key,Request.Form(key)
			else
				POP_MVC.dict.edit Form2Dict,key,CStr(Request.Form(key))
			end if
		next
	End Function
	
	' 得到控制器名称
	Public Function get_ctrl_name(url)
		dim arr : arr = split(url,"/")
		dim ret: ret = POP_MVC.Url.get_ctrl_name()
		dim count : count = ubound(arr)
		
		if count = 1 then	
			ret = POP_MVC.ucfirst(arr(0))
		end if
		get_ctrl_name = ret
	End Function
  
	' 得到操作名称
	Public Function get_action_name(url)
		dim arr : arr = split(url,"/")
		get_action_name = arr( UBound(arr) )
	End Function
	
	Sub Action( url )
		dim c_,a_
		c_ = c : a_ = a
		c = get_ctrl_name(url)
		a = get_action_name(url)
		action_count = 0
		call Action_(c,a)
		action_count = 0
		c = c_ : a = a_
		isExecuteExtends = False
	End Sub
	
	Function Model(ByRef tableName)	
		set Model = import("POPASP_MODEL").Create(tableName)
	End Function
  
	Function getMvcDir()
		getMvcDir = mvc_dir
	End Function
	
	Sub apt_clear
		Application.Contents.RemoveAll
	End Sub
  
	Public Property Set setConfig( byval key, byref val )
		dict.edit config,key,val
	End Property
  
	'获取某个参数
	Public Property Get getConfig(byval key)
		dim arr,i,str
		if isNull(key) Then
			set getConfig = config		
		Else 			
			if inStr( key , "." ) > 0 Then				
				arr = split(key,".")
				str = "POP_MVC.config"				
				for i = 0 to ubound(arr)
					str = str & "(""" & arr(i) & """)"
				next
				Execute "getConfig = " & str			
			elseif config.Exists( key ) Then				
				If isObject( config(key) ) Then				
					set getConfig = config( key )
				else
					getConfig = POP_MVC.config(key)
				End if
			Else
				getConfig = Empty
			End If			
		End if    
	End Property
	
	Public Sub Unset( ByRef obj )
		if isObject( obj ) Then
			if TypeName(obj) = "Recordset" Then
				obj.close
			End If
			set obj = nothing
		elseif TypeName(obj) = "String" Then
			select case obj
				case "k","K","K_","k_"
					dict_auto_key = 0
			End select
		End if
	End Sub
	
	Function isScalar( byref opt )
		dim label : label = TypeName(opt)
		isScalar = (label = "String" OR label = "Integer" OR label = "Long" OR label = "Double" OR label = "Boolean")
	End Function
  
	'获取控制器文件的路径
	Function get_ctrl_path( byVal ctrl_name )
		if ctrl_name = C_("SYSTEM_MODULE") Then
			get_ctrl_path = mvc_dir & "Tpl/" & ctrl_name &"Action.class.asp"
		else
			get_ctrl_path = APP_PATH & "/Controller/" & ctrl_name & "Action.class.asp"
		end if
	End Function

	public Sub ajax( byval input )
		if File.isExists(  "./" & "ajax.txt" ) Then
			Call Easp.fso.AppendFile( "./" & "ajax.txt" , Easp.Str.toString(input) & vbCrLf )
		Else 
			Call Easp.Fso.CreateFile("./" & "ajax.txt",Easp.Str.toString(input) & vbCrLf  )
		End If		
	End Sub
  
	'控制器文件不存在时的处理
	Private Sub ctrl_file_not_exists_handler
		dim c,a
		c = C_("EMPTY_MODULE")
		a = C_("DEFAULT_ACTION")
		url.setConfig "ctrlName",c
		url.setConfig "actionName",a
		
		if File.isFile( get_ctrl_path( c ) ) Then
			Call Action_(c,a)
		else
			Response.write "您访问的网页不存在"
			Call F_( "没有找到类文件"""  & get_ctrl_path( c ) & """" )
		End If
	End Sub
  
	'控制器的类在文件中找不到到的处理
	Private Sub ctrl_not_exists_handler
		call [Exit]("在控制器文件中并未定义相应的控制器")
	End Sub
  
	'方法在控制器中找不到的处理
	Private Sub method_not_exists_handler
		Select case Err.number
			case "438"
				echo "未定义的方法"
			case else
				echo Err.number & Err.Source & Err.Description 
		end Select
	End Sub
  
	'控制器代码写错时的处理
	Private Sub ctrl_code_error_handler
		echo Err.number & Err.Source & Err.Description 
	End Sub
  
	'输出
	Public Sub echo( str )
		Response.write str & "<br />"
	End Sub
  
	'获取文件内容
	Function file_get_contents( ByVal filePath )
		on error resume next
		dim startTime : startTime = timer()
		Dim o_strm, tmpStr,p
		p = Server.MapPath(filePath)
		  Set o_strm = Server.CreateObject("ADODB.Stream")
		  With o_strm
			.Type = 2
			.Mode = 3
			.Open
			.LoadFromFile p
			.Charset = "UTF-8"
			.Position = 2
			tmpStr = .ReadText
			.Close
		  End With
		  Set o_strm = Nothing
		  tmpStr = Replace(tmpStr, "^\uFEFF", "" , 1,1,0)
		file_get_contents = tmpStr
		call pushTime( startTime , "read file " & filePath )
	End Function
	
	' 给文件写入内容，如果文件不存在，则尝试创建
	Function file_put_contents(filePath,content)
		on error resume next
		dim oStream , startTime : startTime = timer()
		content = Replace(content, "^\uFEFF", "" , 1,1,0)
		
		filePath = Replace( filePath, "/" , "\" )
		file_put_contents = CreateFolder( Left(filePath,InstrRev(filePath,"\")-1) )

		if file_put_contents Then
			Set oStream = Server.CreateObject("ADODB.Stream")
			With oStream
				.Type = 2	'以本模式读取
				.mode = 3
				.Open()
				.Charset = "utf-8"
				.Position = .Size

				.WriteText(content)
				.SaveToFile realPath(filePath),2

				.Flush
				.Close
			End With
			Set oStream=Nothing

			file_put_contents = iif((Err.Number = 0),True,False)		
		end if
		call pushTime( startTime , "write file " & filePath)
		call L_("写入文件 " & filePath & " 失败")
	end Function
	
	'//自动生成文件夹路径
	Function CreateFolder( ByVal path )
		on error resume next
		Dim i , folder
		CreateFolder = True
		'//看看是否已经存在目录
		path = realPath(path)
		If fso.FolderExists(path) Then
			Exit Function
		Else
			path = Replace(path,"/","\")
			path = Split(path,"\")
		For i = 0 To Ubound(path)
			folder = folder & path(i) & "\"	
			If Not fso.folderExists(folder) Then
				fso.CreateFolder(folder)
			End If
		Next		 
			CreateFolder = iif((Err.Number = 0),True,False)
		End If
		
		call L_("创建目录 " & path & " 失败")
	End Function
	
	' 从asp文件中取得内容，并且删除第一个与最后一个出现在asp代码标记
	Function asp_get_contents ( file )
		dim str,start_,end_
		str		= file_get_contents(file)
		
		start_	= InStr(str,"<" & "%")
		end_	= InStrRev( str,"%" & ">" )
		
		str= mid(str,start_ + 2,end_-4) 
		
		asp_get_contents = str
		
		if  LCase(right(file,len( "popasp_string.class.asp" ))) = "popasp_string.class.asp" Then
			asp_get_contents = Replace( asp_get_contents , "'POPASP_REPLACE_CLASS_CODE_POPASP'" , file_get_contents( mvc_dir & "Tpl/code_string.txt" ) )
		end if
		
		if  LCase(right(file,len( "popasp_arr.class.asp" ))) = "popasp_arr.class.asp" Then
			asp_get_contents = Replace( asp_get_contents , "'POPASP_REPLACE_CLASS_CODE_POPASP'" , file_get_contents( mvc_dir & "Tpl/code_array.txt" ) )
		end if
		
		if  LCase(right(file,len( "popasp_dictionary.class.asp" ))) = "popasp_dictionary.class.asp" Then
			asp_get_contents = Replace( asp_get_contents , "'POPASP_REPLACE_CLASS_CODE_POPASP'" , file_get_contents( mvc_dir & "Tpl/code_dictionary.txt" ) )
		end if
		
		if  LCase(right(file,len( "popasp_access.class.asp" ))) = "popasp_access.class.asp" OR LCase(right(file,len( "popasp_sqlite3.class.asp" ))) = "popasp_sqlite3.class.asp" OR LCase(right(file,len( "popasp_excel.class.asp" ))) = "popasp_excel.class.asp" Then
			asp_get_contents = Replace( asp_get_contents , "'POPASP_REPLACE_CLASS_CODE_POPASP'" , file_get_contents( mvc_dir & "Tpl/code_db.txt" ) )
			asp_get_contents = Replace( asp_get_contents , "'POPASP_REPLACE_CLASS_PARSEWHERE_POPASP'" , file_get_contents( mvc_dir & "Tpl/code_db_parsewhere.txt" ) )
			asp_get_contents = Replace( asp_get_contents , "'POPASP_REPLACE_CLASS_PARSEOPTIONS_POPASP'" , file_get_contents( mvc_dir & "Tpl/code_db_parseoptions.txt" ) )
		end if
	End Function
	
	' 引入文件 popasp_application.class.asp
	Private Sub import_application
		Dim apt_key
		if isEmpty( apt ) Then	'如果还没有加载application类
			if not is_empty(C_("APPLICATION_ON")) then
				' 取得键名，必须与 apt.getKey() 获取的相一致
				apt_key = getConfig("APPLICATION_PREFIX") & get_class_in_apt_key("POPASP_APPLICATION")
				
				' 如果没有存到 Application中，则先存至 Application中
				if isEmpty( Application.Contents(apt_key) ) Then
					Application.Contents(apt_key) = asp_get_contents( get_mvc_class_path("POPASP_APPLICATION") )
				End If
				Execute Application.Contents(apt_key)
			else 
				Execute  asp_get_contents( get_mvc_class_path("POPASP_APPLICATION") )
			End If
			set apt = new POPASP_APPLICATION
		End if	
	End Sub
	
	Private sub show_page_trace
		if import("POPASP_CONTROLLER").isAjax() then
			exit sub
		end if	
	
		Call G_("viewEndTime")
		if is_empty( C_("SHOW_PAGE_TRACE") ) then
			if not is_empty( C_("APP_DEBUG") ) and is_localhost() then
				Response.Write Chr(13) & Chr(10) & "<!-- POPASP MVC : http://www.popasp.com  |  Spent: " & G_( array("beginTime","viewEndTime") ) & " ms " & "-->"
			end if
			exit sub
		end if	

		Call import("POPASP_PAGETRACE").show()	
	end sub
	
	Private Function get_mvc_class_path(class_name)		
		get_mvc_class_path = mvc_dir & LCase(class_name) & ".class.asp"		
	End Function
	
	Private Function get_class_in_apt_key( class_name )
		get_class_in_apt_key = LCase(class_name) & ".class.asp"
	End Function
  
	' 引入类文件或控制器文件
	Function import(class_name)
		on error resume next
		'将每个生成的对象都保存到dClass中，如果dClass存在这个对象，则直接取出
		if dClass.Exists(class_name) Then
			set import = dClass(class_name) : exit Function
		end if
		

		
		'如果不存在，则第一次实例化该对象，达到单例模式的目的
		execute get_import_asp(class_name)
		if err.number <> 0 Then
			if not is_empty(C("APP_DEBUG")) Then
				call [Exit]( class_name & "类中代码有误:" & err.number & "," & err.description)
			end if
		end if
		
		Execute "Set dClass(""" & class_name & """) = New " & class_name

		set import = dClass(class_name)
	End Function
	
	Sub [exit]( byref str )
		Response.write str
		call quit
	End Sub
	
	Sub quit
		err.clear
		on error resume next
		dim key,key2
		
	
		
		if isObject( dMSSoft ) Then
			for each key in dMSSoft
				if isObject( dMSSoft(key) ) Then
					dMSSoft(key).quit
					set dMSSoft(key) = nothing
				end if
			next
		end if
		
		if isObject( dbTool ) Then
			'自动关闭Recordset资源
			for each key in  dSql
				if dSql(key).exists("rs") Then
					 dSql(key)("rs").close : set  dSql(key)("rs") = nothing
				end if
			next
			'自动关闭数据库链接
			if isObject( dbTool.conn ) Then
				dbTool.conn.close
				set dbTool.conn = nothing
			End if
			set dbTool = nothing
		end if		
		
		if isObject( dModel ) Then
			for each key in dModel
				if isObject( dModel(key) ) then
					if dModel(key).Exists("db") then
						set dModel(key).db = nothing
					end if
					
					if dModel(key).Exists("that") then
						set dModel(key).that = nothing
					end if
				end if
			next
			set dModel = nothing
		end if
		
		if isObject( dClass ) then
			for each key in dClass
				if isObject( dClass(key) ) then
					if key = "POPASP_DATABASE_TOOL" Then
						'自动关闭Recordset资源
						for each key2 in  dSql
							if dSql(key2).exists("rs") Then
								 dSql(key2)("rs").close : set  dSql(key2)("rs") = nothing
							end if
						next
						'自动关闭数据库链接
						if isObject( dbTool.conn ) Then
							dbTool.conn.close
							set dbTool.conn = nothing
						End if
						set dbTool = nothing
					end if					
					
					
					set dClass(key) = Nothing
				end if	
			next
			set dClass = Nothing
		end if
		
		for each key in dDict
			set dDict(key) = nothing
		next
		set dDict = nothing
		
		if isExit then
			Response.end
		end if
	End sub
	
	
	Function get_import_asp(class_name)		
		dim key
		
		if not is_empty( C_("APPLICATION_ON") ) Then	'开启了 Application 缓存
			call import_application		
			if class_name <> "POPASP_APPLICATION" Then				
				if isPopasp(class_name) Then	'如果是框架的类
					key = get_class_in_apt_key(class_name)
					if Not apt.Exists( key ) Then					
						apt.set key,asp_get_contents( get_mvc_class_path(class_name) )
					End If				
					get_import_asp = apt.get(key)		
				Else '不是框架的类，则应该提供路径
					key = realPath(class_name)
					if Not apt.Exists( key ) Then					
						apt.set key,asp_get_contents( class_name )
					End If				
					get_import_asp = apt.get(key)					
				End if	
			Else
				get_import_asp = apt.get( get_class_in_apt_key("POPASP_APPLICATION") )
			end If
		else	'没有开启 Application 缓存
			if isPopasp(class_name) then	'如果是框架的类
				get_import_asp = asp_get_contents( get_mvc_class_path(class_name) )
			else	'不是框架的类，则应该提供路径
				get_import_asp = asp_get_contents( class_name )
			end if
		end if
	End Function
	
	
	Public Function rs2dict(rs)
		dim i,j,dict,start,sql,arr() : j = 0
		set rs2dict = CreateDict()
		
		if not is_empty( C_("SHOW_PAGE_TRACE") ) Then
			start = timer()	
		end if

		reg.Global = true : reg.MultiLine = False : reg.IgnoreCase = True
		reg.Pattern = "^\s*SELECT\s+TOP\s+1\s+.+|^\s*SELECT\s+.*?LIMIT\s+1\s*;?$"		

		if reg.test(rs.Source) then
			set dict = CreateDict()
			for i = 0 to rs.fields.count-1
				dict( rs.Fields(i).Name ) = rs.Fields(i).Value 
			next						
			set rs2dict = dict
		else
			rs.MoveFirst
			Do While Not rs.BOF And Not rs.EOF
				set dict = CreateDict()
				for i = 0 to rs.fields.count-1
					dict( rs.Fields(i).Name ) = rs.Fields(i).Value 
				next
				rs2dict.add j,dict
				rs.MoveNext
				j = j+1
			Loop
		end if
		
		if not is_empty( C_("SHOW_PAGE_TRACE") ) Then
			set sql = D_
			sql("time") = round((timer() - start) * 1000,0)
			sql("sql") = rs.Source & " ; -- Recordset to Dictionary "
			Me.Dict.Push dSql,"",sql
		end if
		set dict = nothing
	End Function
	
	' 计算个数
	Public Function count( var )
		if isArray(var) Then
			count = ubound(var) + 1
		else
			select case TypeName(var)
				case "String"
					count = Len(var)
				case "Integer","Long","Single","Double","Currency","Decimal","Date","Boolean"
					count = 1
				case "Dictionary","Files","IVariantDictionary","IRequestDictionary"
					count = var.Count
				case "Recordset"
					count = var.RecordCount
				case "ISessionObject"
					count = var.Contents.Count
				case "Empty","Null","Unknown","Nothing","Error"
					count = 0
				case else
					count = 0
			End Select		
		End If
	End Function
	
	' 获取绝对路径
	Function realPath( path )
		if inStr(path,":") > 0 then
			realPath = path
		else
			realPath =Server.mapPath( Replace(  path  ,"/" , "\" ) )
		end if
	End Function
	
	' 执行控制器
	Private Sub Action_(c,a)
		dim className,ctrl_action,template_file,ctrl_str,rej,bool,fc,fd,f1,method_exists,replacement
		on error resume next
		'防止无穷尽循环，如果超过10次，则退出
		if action_count > 10 Then Exit Sub
		action_count = action_count + 1
		method_exists = true
		
		Call F_("准备执行 " & c & "Action." & a)
		
		
		'根据控制器文件是否存在进行相应的处理
		if File.isFile( get_ctrl_path( c ) ) Then	'判断控制器文件是否存在
			bool = true
			' 区分大小写时，看不看文件名大小写是否相同，C_("SYSTEM_MODULE")不区分大小写
			if is_empty(C_("URL_CASE_INSENSITIVE")) and c <> C_("SYSTEM_MODULE") Then
				bool = false
				set fd = fso.getFolder( realPath(APP_PATH & "/Controller/"))
				set fc = fd.files
				for each f1 in fc
					if f1.name = c & "Action.class.asp" Then
						bool = true
						exit for
					end If
				next
				set fc = nothing
				set fd = nothing
			End If
		
			
			' bool为真，则继续向下执行
			if bool Then
				' 记录应用初始化时间
				Call G_("initTime")	
				ctrl_str = get_import_asp(get_ctrl_path( c ))	'得到控制器文件的内容
				
				' 
				replacement = "Action" & vbCrLf & vbTab & "Public that,parent"
				
				' C_("TMPL_CACHE_ACTION")不为空，则添加页面静态化函数
				if C_("TMPL_CACHE_ACTION") <> "" Then 
					replacement = replacement & vbCrLf
					replacement = replacement & vbCrLf & vbTab & "Sub " & C_("TMPL_CACHE_ACTION")
					replacement = replacement & vbCrLf & vbTab & vbTab & "if is_empty(S_( C_(""TMPL_CACHE_ACTION"") )) Then Exit Sub"
					replacement = replacement & vbCrLf & vbTab & vbTab & "Call that.template.cache_url() : response.end"
					replacement = replacement & vbCrLf & vbTab & "End Sub"
					replacement = replacement & vbCrLf
				end if

				ctrl_str = Replace(ctrl_str,"Action" ,replacement ,1,1,0) '添加that与parent		
				
				className = UCFirst( LCase(c) ) & "Action"		'标准的控制器名称	
				
				Execute ctrl_str	'运行类
				
				If Err.number <> 0 Then
					if Not is_empty( C_("APP_DEBUG") ) Then
						call L_( "控制器" & c & "Action" & "中代码有误" )
						call quit
					else
						Call ctrl_code_error_handler
					end if
				End If
				
				'实例化类，如果没有该类进行处理
				Execute "set ctrl_action = new " & className

				If Err.number <> 0 Then
					call L_( "控制器" & c & "Action" & "中代码有误" )
					Call ctrl_not_exists_handler
				End If
				
				set rej = import("POPASP_REJECTION").Parse( className )	'解析控制器的映射	
				
				
				
				set ctrl_action.that = import("POPASP_CONTROLLER")	 '实例化控制器父类

				
				' 如果有继承关系，则执行父类方法 initialize
				if isExecuteExtends AND rej.Exists("extends") Then	
					Call Action_( left(rej("extends"), Len(rej("extends"))-6 ), "initialize" )
					set ctrl_action.parent = objExtendsClass
				End If	
				
				set objExtendsClass = ctrl_action		
			
				' 第一次执行 intialize 方法
				if isExecuteExtends AND rej("public_method").Exists("initialize") Then
					Call F_("开始执行 " & className & ".initialize")
					Execute "call ctrl_action.initialize"
					Call F_("执行结束 " & className & ".initialize")
				End If
				
				
				' 前面已经加载过一次initialize了
				'isExecuteExtends = false
				if LCase(a) <> "initialize" Then

					'加载方法，如果没有该方法进行处理
					if rej("public_method").Exists( LCase(a) ) Then							
						if (Not is_empty(C_("URL_CASE_INSENSITIVE"))) OR ( is_empty(C_("URL_CASE_INSENSITIVE")) AND rej("public_method")(LCase(a)) = a ) Then
							
							
							Call F_("开始执行 " & className & "." & a)
							Execute "call ctrl_action." & a	
							
							Call F_("执行结束 " & className & "." & a)
						else
							method_exists = false				
						End If	
						
					Else 					
						'如果方法不存在，但是模板文件存在，也让其显示
						template_file = APP_PATH & "/TPL/" & c & "/" & a & getConfig("TMPL_TEMPLATE_SUFFIX")
						if File.isExists(template_file)  Then
							bool = true
							if is_empty(C_("URL_CASE_INSENSITIVE")) Then	'区分大小写时，
								bool = false
								set fd = fso.getFolder( realPath(APP_PATH & "/TPL/" & c & "/") )
								set fc = fd.files
								for each f1 in fc
									if f1.name = a & getConfig("TMPL_TEMPLATE_SUFFIX") Then
										bool = true
										exit for
									end If
								next
								set fc = nothing
								set fd = nothing
							End If
							
							if bool then						
								Err.clear
								ctrl_action.that.display0 a,""
							else
								method_exists = false
							End If
						Else 					
							method_exists = false
						End If	
						set ctrl_action.that = nothing
					End If
					
					if err.number<>0 Then
						Call L_("")
						Response.end
					End If
					
					if not method_exists Then
						Call F_( "没有函数 "  & className & "." & a )
						if rej("public_method").Exists( C_("EMPTY_ACTION") ) Then
							isExecuteExtends = false
							Call Action_( c,C_("EMPTY_ACTION")  )
						else
							Call F_( "没有函数 "  & className & "." & C_("EMPTY_ACTION") )
							Call ctrl_file_not_exists_handler
						End If
					End If
				End If			
			Else
				Call ctrl_file_not_exists_handler
			End If
		Else	'没有找到类文件		
			' 记录应用初始化时间
			Call G_("initTime")
			Call F_( "没有找到类文件"""  & get_ctrl_path( c ) & """" )
			Call ctrl_file_not_exists_handler
		End if	
		Call L_("")
	End Sub
	
	'不缓存页面信息
	Public Sub NoCache()
		Response.Expires = 0
		Response.ExpiresAbsolute = Now() - 1
		Response.CacheControl = "no-cache"
		Response.AddHeader "Expires",Now() - 1
		Response.AddHeader "Pragma","no-cache"
		Response.AddHeader "Cache-Control","private, no-cache, must-revalidate"
	End Sub
  
	public sub start
		dim struct
		call init
		set struct = import("POPASP_STRUCTRUE")
		call struct.handler
		
		c = Url.get_ctrl_name()		
		a = Url.get_action_name()		
		call Url.set_tmpl_config			
		isExecuteExtends = True
		action_count = 0
		
		Call Action_(c,a)
		action_count = 0
		
		Call show_page_trace()
		isExecuteExtends = False		
		set struct = nothing
	end sub  
End Class
%>